Report full data path in incompatible-update invariant messages#689
Draft
vladar wants to merge 2 commits into
Draft
Report full data path in incompatible-update invariant messages#689vladar wants to merge 2 commits into
vladar wants to merge 2 commits into
Conversation
When an incompatible-update invariant fires on a non-addressable value (a CompositeNull/CompositeUndefined, whose source data is null/undefined), getDataPathForDebugging cannot locate it, so the message fell back to only the last field/index segment (e.g. 'value' instead of 'listContainer.items.0.value'). Thread the failing value's parent chunk (always an addressable ObjectChunk/CompositeListChunk) into the location and derive the path from the parent plus the field/index step, so the full path is reported even for non-addressable values. The enclosing (in <TypeName>) node is likewise resolved from the parent when needed. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…ution resolveFailurePath now derives the path from a nested property (location.field.dataKey) rather than an eagerly-captured primitive, so a malformed field could throw while building the invariant message and mask the real invariant. Wrap the whole derivation in try/catch, consistent with the other best-effort diagnostic helpers (chunkPath, nodeTypeClause), so path resolution can never throw over the invariant it is reporting. Add a regression test that forces findParent to throw during both path and enclosing-node resolution and asserts the invariant message still surfaces. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
📊 Benchmark Analysis Report✅ No significant performance changes detected Threshold: 5% change Updated: 2026-07-10T16:49:14.900Z |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Incompatible-update invariants surfaced in telemetry with truncated paths, e.g.:
But
meetingExtensionDefinitionis not a root field of that operation; it is nested several levels deep. The reported path was just the last segment, which makes these errors much harder to diagnose.Root cause
When the failing value is a
CompositeNull/CompositeUndefined, its source data isnull/undefined, sogetDataPathForDebuggingcannot locate it in the tree. The message builder then fell back todescribeLocation, which only knew the immediate field/index, dropping the rest of the path.Approach
Thread the failing value's parent chunk (always an addressable
ObjectChunk/CompositeListChunk) into the update location, and derive the path from the parent plus the field/index step. This yields the full path (e.g.listContainer.items.0.value) even when the failing value itself is not addressable. The enclosing(in <TypeName>)node clause is likewise resolved from the parent when the value itself can't anchor it.Failing gracefully
These builders run while the cache is already in an inconsistent state, so they must never throw over the invariant they are reporting. Every path/type helper is wrapped in try/catch. Because this change moved path derivation from an eagerly-captured primitive to a nested property access (
location.field.dataKey),resolveFailurePathis now wrapped as well, matching the existing defensive style. If resolution throws, the message drops the path/node clause and still surfaces the invariant.Tests
CompositeNull.findParentthrows during both path and enclosing-node resolution.The tests use a synthetic query; the private operation from telemetry is not referenced.